package com.icee.myth.common.channelContext;

import com.icee.myth.common.channelHandler.HttpServerHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;

import java.util.ArrayList;
import java.util.concurrent.LinkedTransferQueue;


/**
 * @author liuxianke
 */
public class ChannelContext {

    private static final int MAX_FLUSH_MESSAGE_NUM_PER_WRITING = 1024;
    protected final LinkedTransferQueue<Object> messageQueue = new LinkedTransferQueue<Object>();

    /* channel to server */
    protected Channel channel = null;
    protected boolean isActive = false;

    public ChannelContext() {
    }

    public void setChannel(Channel channel) {
        if (channel != null) {
            this.channel = channel;
            isActive = true;
        }
    }

    public boolean isActive() {
        return isActive;
    }

    /**
     * writeAndFlush
     */
    public final void write(Object message) {
        if (isActive) {
//            messageQueue.add(message);
            ChannelFuture f = this.channel.writeAndFlush(message);
            if (null != f) {
                f.addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (null != future) {
                            if (future.isSuccess()) {
                                System.out.println("writeAndFlush ok");
                            } else {
                                System.err.print("writeAndFlush fail:");
                                future.cause().printStackTrace();
                            }
                        }
                    }
                });
            }
        }
    }

    public void flush() {
        if (isActive) {
            Object msg = messageQueue.poll();
            if (msg != null) {
                boolean finish = false;
                while (!finish) {
                    final ArrayList<Object> messages = new ArrayList<Object>(MAX_FLUSH_MESSAGE_NUM_PER_WRITING);
                    while (msg != null && messages.size() < MAX_FLUSH_MESSAGE_NUM_PER_WRITING) {
                        channel.writeAndFlush(msg);
                        messages.add(msg);
                        msg = messageQueue.poll();
                    }
                    finish = messages.size() < MAX_FLUSH_MESSAGE_NUM_PER_WRITING;
//                    channel.writeAndFlush(messages);
                    //通过将操作封装成独立的 Task 由 NioEventLoop 统一执行，而不是业务线程直接操作
//                    if (channel.eventLoop().inEventLoop()) {
//                        channel.write(messages);
//                    } else {
//                        channel.eventLoop().execute(new Runnable() {
//                            @Override
//                            public void run() {
//                                channel.write(messages);
//                            }
//                        });
//                    }
                }
//                channel.flush();
            }
        }

    }

    /* write，未flush */
    public ChannelFuture fastWrite(Object message) {
        if (isActive) {
            return channel.writeAndFlush(message);
        } else {
            return null;
        }
    }

    public ChannelFuture close() {
        if (isActive) {
            isActive = false;
            messageQueue.clear();
            return channel.close();
        } else
            return null;
    }

    public boolean isChannel(Channel channel) {
        return this.channel == channel;
    }

    //    public int getId() {
//        if(isActive)
//            return this.channel.getId();
//        else
//            return -1;
//    }
//    public String getId() {
//        if (isActive)
//            return this.uuid.toString();
//        else
//            return null;
//    }

    public int getRemoteIP() {
        return HttpServerHandler.getRemoteIP(channel);
    }

}
